//
// Created by ttao on 2022/7/25.
//

#ifndef COMPUTER_DTS_H
#define COMPUTER_DTS_H
/*
 * eg dts数据结构操作
    dts d1 = dtsnew("hello");
 */
#include <stdint.h>
#include <stddef.h>
#include <limits.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include <unix/http_tmalloc.h>
#include "lstring.h"
#define DTS_MAX_PREALLOC (1024*1024)
// dts 的特点二进制安全
typedef char* dts; // 这个指针指向 dts 中的buf
// __attribute__ ((__packed__)) 取消编译器对齐\
// sizeof(dts##T)获取真实长度
// len 字符串的真实长度 因为我们的字符串不再以 ‘\0’ 结尾所以需要保存长度
// alloc 预先分配的内存长度 这个长度一定大于len
// flag 只使用底三位 代表类型
struct __attribute__ ((__packed__)) dts8 {
    uint8_t len;
    uint8_t alloc;
    unsigned char flag;
    char buf[];
};
struct __attribute__ ((__packed__)) dts16 {
    uint16_t len;
    uint16_t alloc;
    unsigned char flag;
    char buf[];
};
struct __attribute__ ((__packed__)) dts32 {
    uint32_t len;
    uint32_t alloc;
    unsigned char flag;
    char buf[];
};
struct __attribute__ ((__packed__)) dts64 {
    int64_t len;
    int64_t alloc;
    unsigned char flag;
    char buf[];
};

#define DTS_FLAG_8    0
#define DTS_FLAG_16   1
#define DTS_FLAG_32   2
#define DTS_FLAG_64   3
#define DTS_FLAG_MASK 7

// 因为d 指向buf

#define DTS_VAR(T, d) struct dts##T *dt = (void*) ((d) - (sizeof(struct dts##T)))
#define DTS_DATA(T, d) ((struct dts##T *)((d)- sizeof(struct dts##T)))
#define DTS_LEN(T, d) DTS_DATA(T, d)->len
#define DTS_ALLOC(T, d) DTS_DATA(T, d)->alloc

#define d_realloc_usable trealloc_usable
#define d_malloc_usable tmalloc_usable

static inline size_t dtslen(const dts d)
{
    unsigned char flag = d[-1];         // 因为d的地址是指向buf的所以向数组反方向偏移一个字符就是flag的区域
    switch (flag&DTS_FLAG_MASK) {
        case DTS_FLAG_8:
            return DTS_LEN(8, d);
        case DTS_FLAG_16:
            return DTS_LEN(16, d);
        case DTS_FLAG_32:
            return DTS_LEN(32, d);
        case DTS_FLAG_64:
            return DTS_LEN(64, d);
    }
    return 0;
}


static inline void setdtslen(const dts d, size_t newlen)
{
    unsigned char flag = d[-1];
    switch (flag&DTS_FLAG_MASK) {
        case DTS_FLAG_8:
            DTS_LEN(8, d) = newlen;
            break;
        case DTS_FLAG_16:
            DTS_LEN(16, d) = newlen;
            break;
        case DTS_FLAG_32:
            DTS_LEN(32, d) = newlen;
            break;
        case DTS_FLAG_64:
            DTS_LEN(64, d) = newlen;
            break;
    }
}



static inline void incdtslen(const dts d, size_t inc)
{
    unsigned char flag = d[-1];
    switch (flag&DTS_FLAG_MASK) {
        case DTS_FLAG_8:
            DTS_LEN(8, d) += inc;
            break;
        case DTS_FLAG_16:
            DTS_LEN(16, d) += inc;
            break;
        case DTS_FLAG_32:
            DTS_LEN(32, d) += inc;
            break;
        case DTS_FLAG_64:
            DTS_LEN(64, d) += inc;
            break;
    }
}


static inline size_t dtsalloc(const dts d)
{
    unsigned char flag = d[-1];         // 因为d的地址是指向buf的所以向数组反方向偏移一个字符就是flag的区域
    switch (flag&DTS_FLAG_MASK) {
        case DTS_FLAG_8:
            return DTS_ALLOC(8, d);
        case DTS_FLAG_16:
            return DTS_ALLOC(16, d);
        case DTS_FLAG_32:
            return DTS_ALLOC(32, d);
        case DTS_FLAG_64:
            return DTS_ALLOC(64, d);
    }
    return 0;
}


static inline void setdtsalloc(const dts d, size_t newalloc)
{
    unsigned char flag = d[-1];
    switch (flag&DTS_FLAG_MASK) {
        case DTS_FLAG_8:
            DTS_ALLOC(8, d) = newalloc;
            break;
        case DTS_FLAG_16:
            DTS_ALLOC(16, d) = newalloc;
            break;
        case DTS_FLAG_32:
            DTS_ALLOC(32, d) = newalloc;
            break;
        case DTS_FLAG_64:
            DTS_ALLOC(64, d) = newalloc;
            break;
    }

}

static inline size_t dtsavail(const dts d)
{
    unsigned char flag = d[-1];
    switch (flag&DTS_FLAG_MASK) {
        case DTS_FLAG_8:{
            DTS_VAR(8, d);
            return dt->alloc - dt->len;
        }
        case DTS_FLAG_16:{
            DTS_VAR(16, d);
            return dt->alloc - dt->len;
        }
        case DTS_FLAG_32:{
            DTS_VAR(32, d);
            return dt->alloc - dt->len;
        }
        case DTS_FLAG_64:{
            DTS_VAR(64, d);
            return dt->alloc - dt->len;
        }
    }
}
dts dtsempty(void);
void dtsclear(dts s);
dts dtsnewlen(const char *init, size_t initlen);
dts dtstrynewlen(const char *init, size_t initlen);
dts dtsnew(const char * init);
dts dtsresize(dts ptr, const size_t size);
dts dtscpystr(dts d, const char *t);
dts dtscpy(dts desc, dts sre);
dts dtscpylen(dts desc, char* sre, int len);
dts dtsdup(const dts s);
dts dtscat(dts s, const char *t);
dts dtscatlen(dts s, const char *t, size_t len);
dts dtscatsds(dts before, dts after);
int dtsrange(dts s, size_t start, size_t end);
dts dtstrim(dts s, const char *cset);
int dtscmp(const dts s1, const dts s2);
int dtscasecmp(const dts s1, const dts s2);
int dtscmpstr(const dts s1, const char* s2);
int dtscasecmpstr(const dts s1, const char* s2);
void dtstoupper(dts s);
void dtstolower(dts s);
size_t dtsfree(dts s);
#endif //COMPUTER_DTS_H
